package com.sduept.cime;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CimeParser {

    public static void main(String[] args) throws Exception {
        String content = "";

    }

    private String _content;
    private String _head;
    
    
    /**
               * 解析文件内容为List<Cime>格式
     *
     * @param content
     * @return
     */
    public HashMap<String,Cime> parseCimeFile(String fileName) {
		System.out.println(new Date().toString());
		BufferedReader br;
		String row = "";

        HashMap<String,Cime> cimeList = new HashMap<String,Cime>();
        List<String> model = new ArrayList<String>();
        List<List<String>> modelList = new ArrayList<List<String>>();
        boolean flag = false;
        
		try {
			br = new BufferedReader(new FileReader(fileName));
			while(br.ready()) {
				row = br.readLine().trim();
	            if (row.startsWith("<") && row.endsWith(">") && !row.startsWith("<!") && !row.startsWith("</")) {
	                model.add(row);
	                flag = true;
	                continue;
	            }
	            if (flag) {
	                if (row.startsWith("</") && row.endsWith(">")) {
	                    flag = false;
	                    model.add(row);
	                    List<String> list = new ArrayList<String>(model);
	                    modelList.add(list);
	                    model.clear();
	                    continue;
	                } else if (row.startsWith("<") && row.endsWith(">")) {
	                    flag = false;
	                    List<String> list = new ArrayList<String>(model);
	                    modelList.add(list);
	                    model.clear();
	                    continue;
	                }
	            }
	            if (flag && !row.startsWith("<")) {
	                model.add(row);
	            }
			}
	        for (List<String> cimeModel : modelList) {
	            Cime cime = new Cime();
	            //cime.setHead(headMap);
	            List<List<String>> list = new ArrayList<List<String>>();
	            for (String rowModel : cimeModel) {
	                if (rowModel.startsWith("<") && !rowModel.startsWith("</") && rowModel.endsWith(">")) {
	                    String fieldName = rowModel.substring(rowModel.indexOf("<") + 1, rowModel.length() - 1);
	                    cime.setName(fieldName);
	                }
	                if (rowModel.startsWith("@")) {
	                    String[] columnNames = rowModel.replaceFirst("@", "").split("\\s+");
	                    cime.setColumnNames(columnNames);
	                }
	                if (rowModel.startsWith("%")) {
	                    String[] columnTypes = rowModel.replaceFirst("%", "").split("\\s+");
	                    cime.setColumnTypes(columnTypes);
	                }
	                if (rowModel.startsWith("#")) {
	                    rowModel = rowModel.replaceFirst("#", "").trim();
	                    List<String> datas = new ArrayList<String>();
	                    Pattern p = Pattern.compile("\'(.*?)\'|\\S+");
	                    Matcher m = p.matcher(rowModel);
	                    while (m.find()) {
	                        datas.add(m.group());
	                    }
	                    list.add(datas);
	                    cime.setColumnsValues(list);
	                }
	            }
	            cimeList.put(cime.getName(),cime);
	        }
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return cimeList;

    }
    /**
               * 解析文件内容为List<Cime>格式
     *
     * @param content
     * @return
     */
    public List<Cime> parseCime(String content) {
        Map<String, String> headMap = cimeHead(content);
        List<Cime> cimeList = new ArrayList<Cime>();
        _content = content;
        _content = _content.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
        String[] strArr = null;
        if (_content.contains("\n")) {
            strArr = _content.split("\n");
        }
        if (strArr == null) {
            return null;
        }
        List<String> model = new ArrayList<String>();
        List<List<String>> modelList = new ArrayList<List<String>>();
        boolean flag = false;
        for (String line : strArr) {
            String row = line.trim();
            if (row.startsWith("<") && row.endsWith(">") && !row.startsWith("<!") && !row.startsWith("</")) {
                model.add(row);
                flag = true;
                continue;
            }
            if (flag) {
                if (row.startsWith("</") && row.endsWith(">")) {
                    flag = false;
                    model.add(row);
                    List<String> list = new ArrayList<String>(model);
                    modelList.add(list);
                    model.clear();
                    continue;
                } else if (row.startsWith("<") && row.endsWith(">")) {
                    flag = false;
                    List<String> list = new ArrayList<String>(model);
                    modelList.add(list);
                    model.clear();
                    continue;
                }
            }
            if (flag && !row.startsWith("<")) {
                model.add(row);
            }
        }
        for (List<String> cimeModel : modelList) {
            Cime cime = new Cime();
            cime.setHead(headMap);
            List<List<String>> list = new ArrayList<List<String>>();
            for (String row : cimeModel) {
                if (row.startsWith("<") && !row.startsWith("</") && row.endsWith(">")) {
                    String fieldName = row.substring(row.indexOf("<") + 1, row.length() - 1);
                    cime.setName(fieldName);
                }
                if (row.startsWith("@")) {
                    String[] columnNames = row.replaceFirst("@", "").split("\\s+");
                    cime.setColumnNames(columnNames);
                }
                if (row.startsWith("%")) {
                    String[] columnTypes = row.replaceFirst("%", "").split("\\s+");
                    cime.setColumnTypes(columnTypes);
                }
                if (row.startsWith("#")) {
                    row = row.replaceFirst("#", "").trim();
                    List<String> datas = new ArrayList<String>();
                    Pattern p = Pattern.compile("\'(.*?)\'|\\S+");
                    Matcher m = p.matcher(row);
                    while (m.find()) {
                        datas.add(m.group());
                    }
                    list.add(datas);
                    cime.setColumnsValues(list);
                }
            }
            cimeList.add(cime);
        }
        return cimeList;
    }

    public <T> List<T> fromCime(String content, String fieldName, Class<T> mediatorClass) throws Exception {
        List<T> objectList = new ArrayList<T>();
        Field[] fields = mediatorClass.getFields();
        _content = content;
        String[] strArr = null;
        int index = content.indexOf(fieldName);
        if (index != -1) {
            _content = _content.split(fieldName)[1];
            String str = _content.substring(0, _content.indexOf("</"));
            str = str.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
            if (str.indexOf("\n") != -1) {
                strArr = str.split("\n");
            }
        }
        if (strArr == null) {
            return null;
        }
        Map<Integer, String> map = new HashMap<Integer, String>();
        boolean flag = true;//标记位，兼容 后面数据中，存在@符号的情况
        for (String row : strArr) {
            if (row.indexOf("@") == 0 && flag) {//获取属性名，对应的顺序
                String[] attributes = row.split("\\s+");
                map = mappingFieldOrder(attributes, fields, mediatorClass.newInstance());
                flag = false;
                continue;
            }
            if (row.indexOf("#") == 0) {//获取数据，放到对象里
                T object = mediatorClass.newInstance();
                List<String> datas = new ArrayList<String>();
                Pattern p = Pattern.compile("\'(.*?)\'|\\S+");
                Matcher m = p.matcher(row);
                while (m.find()) {
                    datas.add(m.group());
                }
                //String[] datas = row.split("\\s+");//错误的解析不合适，数据行中，存在一对单引号中有空格的情况
                Iterator<Integer> it = map.keySet().iterator();
                while (it.hasNext()) {
                    int order = it.next();
                    int dataOrder = order;
                    //数据行，标准格式，'#'后有一个或者多个空格，后面跟着序号# 1
                    if (datas.get(0).length() == 1) {
                        dataOrder++;
                    }
                    //数据行，非标准格式，山东'#'后没有空格，直接跟着序号，如#1
                    for (int i = 0; i < fields.length; i++) {
                        if (fields[i].get(object) != null) {
                            if (fields[i].get(object).equals(map.get(order))) {
                                if (dataOrder >= datas.size()) {
                                    fields[i].set(object, "''");//没给赋值的情况下，给个''
                                    break;
                                }
                                fields[i].set(object, datas.get(dataOrder));
                                break;
                            }
                        } else {
                            if (fields[i].getName().equals(map.get(order))) {
                                if (dataOrder >= datas.size()) {
                                    fields[i].set(object, "''");//没给赋值的情况下，给个''
                                    break;
                                }
                                fields[i].set(object, datas.get(dataOrder));
                                break;
                            }
                        }
                    }
                }
                objectList.add(object);
            }
        }
        return objectList;
    }

    /**
     * 根据CIME中属性名的顺序，确认对应数据的顺序，使他们关联起来
     * 同时，要兼容标准格式和非标准格式的处理，如#1（非标准格式）和#  1（标准格式）这两种格式
     *
     * @param <T>
     * @param attributes
     * @param fields
     * @return
     * @throws Exception
     * @throws
     */
    private <T> Map<Integer, String> mappingFieldOrder(String[] attributes, Field[] fields, T object) throws Exception {
        Map<Integer, String> map = new HashMap<Integer, String>();
        for (int i = 0; i < attributes.length; i++) {
            for (Field field : fields) {
                //判断是否有默认值，有的话以默认值来匹配
                if (field.get(object) != null) {
                    if (field.get(object).equals(attributes[i])) {
                        map.put(i, attributes[i]);
                    }
                } else {
                    if (attributes[i].equals(field.getName())) {
                        map.put(i, attributes[i]);
                    }
                }
            }
        }
        return map;
    }

    /**
     * 拆分CIME文件头，等号两边放到map中
     *
     * @param content
     * @return
     */
    public Map<String, String> cimeHead(String content) {
        _head = content;
        Map<String, String> hashMap = new HashMap<String, String>();
        String[] strArr = null;
        String sign = "<!";
        int index = _head.indexOf(sign);
        if (index != -1) {
            String str = _head.substring(index + sign.length(), _head.indexOf("!>"));
            strArr = str.split("\\s+");
        }
        if (strArr == null || strArr.length == 0) {
            return null;
        }
        for (String str : strArr) {
            if (str.contains("=")) {
                hashMap.put(str.split("=")[0], str.split("=")[1]);
            }
        }
        return hashMap;
    }

    /**
     * 解析D5000的告警事件数据,自定义数据格式,不是标准的CIME文件格式
     *
     * @param content
     * @param fieldName
     * @param mediatorClass
     * @return
     * @throws Exception
     */
    public <T> List<T> fromD5kEvent(String content, String fieldName, Class<T> mediatorClass) throws Exception {
        List<T> objectList = new ArrayList<T>();
        Field[] fields = mediatorClass.getFields();
        _content = content;
        String[] strArr = null;
        int index = content.indexOf(fieldName);
        if (index != -1) {
            _content = _content.split(fieldName)[1];
            String str = _content.substring(0, _content.indexOf("</"));
            str = str.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
            if (str.indexOf("\n") != -1) {
                strArr = str.split("\n");
            }
        }
        if (strArr == null) {
            return null;
        }
        Map<Integer, String> map = new HashMap<Integer, String>();
        boolean flag = true;//标记位，兼容 后面数据中，存在@符号的情况
        for (String row : strArr) {
            if (row.indexOf("@") == 0 && flag) {//获取属性名，对应的顺序
                String[] attributes = row.split("\\s+");
                map = mappingFieldOrder(attributes, fields, mediatorClass.newInstance());
                flag = false;
                continue;
            }
            if (row.indexOf("#") == 0) {//获取数据，放到对象里
                T object = mediatorClass.newInstance();
                String[] datas = null;
                if (row.contains("\t") && row.contains(" ")) {
                    datas = row.split("\t");//以tab作为分隔符
                } else {
                    datas = row.split("\\s+");
                }
                Iterator<Integer> it = map.keySet().iterator();
                while (it.hasNext()) {
                    int order = it.next();
                    int dataOrder = order;
                    //数据行，d5k自定义格式
                    for (int i = 0; i < fields.length; i++) {
                        if (fields[i].get(object) != null) {
                            if (fields[i].get(object).equals(map.get(order))) {
                                if (dataOrder >= datas.length) {
                                    fields[i].set(object, "''");//没给赋值的情况下，给个''
                                    break;
                                }
                                fields[i].set(object, datas[dataOrder]);
                                break;
                            }
                        } else {
                            if (fields[i].getName().equals(map.get(order))) {
                                if (dataOrder >= datas.length) {
                                    fields[i].set(object, "''");//没给赋值的情况下，给个''
                                    break;
                                }
                                fields[i].set(object, datas[dataOrder]);
                                break;
                            }
                        }

                    }
                }
                objectList.add(object);
            }
        }
        return objectList;
    }

}
